#ifndef __M_EPOLL_H
#define __M_EPOLL_H

typedef struct _epoll_rb_socket ep_rb_tree;

struct epoll_event{
    uint32_t events;
    uint64_t data;
};

enum {
    EPOLLNONE 	= 0x0000,
    EPOLLIN 	= 0x0001,
    EPOLLPRI	= 0x0002,
    EPOLLOUT	= 0x0004,
    EPOLLRDNORM = 0x0040,
    EPOLLRDBAND = 0x0080,
    EPOLLWRNORM = 0x0100,
    EPOLLWRBAND = 0x0200,
    EPOLLMSG	= 0x0400,
    EPOLLERR	= 0x0008,
    EPOLLHUP 	= 0x0010,
    EPOLLRDHUP 	= 0x2000,
    EPOLLONESHOT = (1 << 30),
    EPOLLET 	= (1 << 31)
};


enum {
    EPOLL_CTL_ADD = 1,
    EPOLL_CTL_DEL = 2,
    EPOLL_CTL_MOD = 3,
};


union epoll_data {
    void *ptr;
    int sockid;
    uint32_t u32;
    uint64_t u64;
};

struct epitem {
    RB_ENTRY(epitem) rbn;
    LIST_ENTRY(epitem) rdlink;
    int rdy; //exist in list
    int sockfd;
    struct epoll_event event;
};

struct eventpoll {
    int fd;
    ep_rb_tree rbr;     // 指向红黑树
    int rbcnt;
    LIST_HEAD( ,epitem) rdlist;   // 指向就绪队列
    int rdnum;
    int waiting;
    pthread_mutex_t mtx; //rbtree update
    pthread_spinlock_t lock; //rdlist update
    pthread_cond_t cond; //block for event
    pthread_mutex_t cdmtx; //mutex for cond
    struct eventpoll * next;
    struct eventpoll * prev;
};


int epoll_event_cb(struct eventpoll * ep, int socket_fd, uint32_t event);
int m_epoll_create(int size);
int m_epoll_ctl(int epfd, int op, int sockid, struct epoll_event * ev);
int m_epoll_wait(int epfd, struct epoll_event * events, int max_events, int time_out);
int sockfd_cmp(struct epitem *ep1, struct epitem *ep2)
#endif